using System;
using UnityEngine;

namespace JufGame.MathHelper
{
	[Serializable]
	public class Matrix
	{
		public int Rows => rows;
		public int Columns => columns;
		[SerializeField] private int rows, maxRows;
		[SerializeField] private int columns, maxColumns;

		private float[,] data;
		public Matrix(int rows, int columns)
		{
			this.rows = maxRows = rows;
			this.columns = maxColumns = columns;
			data = new float[rows, columns];
		}
		public Matrix(int rows, int columns, float[,] data)
		{
			this.rows = maxRows = rows;
			this.columns = maxColumns = columns;
			this.data = data;
		}

		public float this[int row, int col]
		{
			get 
			{
				if (data == null)
				{
					LoadData();
				}
				return data[row, col];
			}
			set 
			{
				if (data == null)
				{
					LoadData();
				}
				data[row, col] = value;
			}
		}
		public void SetRows(int newRows)
		{
			if (newRows > 0 && newRows <= maxRows)
				rows = newRows;
		}
		public void SetColums(int newColumns)
		{
			if (newColumns > 0 && newColumns <= maxColumns)
				columns = newColumns;
		}
		/// <summary>
		/// 还原初始行数
		/// </summary>
		public void RevertRows()
		{
			rows = maxRows;
		}
		/// <summary>
		/// 还原初始列数
		/// </summary>
		public void RevertColums()
		{
			columns = maxColumns;
		}
		public void LoadData()
		{
			data = new float[maxRows, maxColumns];
		}

		public static Matrix Multiply(Matrix a, Matrix b)
		{
			if (a.Columns != b.Rows)
				throw new ArgumentException("该矩阵无法进行乘法");
			int i, j, k;
			int resultRows = a.Rows;
			int resultColumns = b.Columns;
			Matrix result = new(resultRows, resultColumns);
			for (i = 0; i < resultRows; i++)
			{
				for (k = 0; k < a.Columns; k++)
				{
					float curA = a[i, k];
					for (j = 0; j < resultColumns; j++)
					{
						result[i, j] += curA * b[k, j];
					}
				}
			}
			return result;
		}

		public static float Multiply_GetMaxMin(ref Vector3 a, Matrix b, bool isMax)
		{
			if (b.Rows != 3)
				throw new ArgumentException("该矩阵无法进行乘法");
			int j, resultColumns = b.Columns;
			float ans = isMax ? float.MinValue : float.MaxValue;
			float curA, tp;

			curA = a.x;
			tp = 0;
			for (j = 0; j < resultColumns; j++)
			{
				tp += curA * b[0, j];
			}
			if (isMax) ans = tp > ans ? tp : ans;
			else ans = tp <ans ? tp : ans;

			curA = a.y;
			tp = 0;
			for (j = 0; j < resultColumns; j++)
			{
				tp += curA * b[0, j];
			}
			if (isMax) ans = tp > ans ? tp : ans;
			else ans = tp <ans ? tp : ans;

			curA = a.z;
			tp = 0;
			for (j = 0; j < resultColumns; j++)
			{
				tp += curA * b[0, j];
			}
			if (isMax) ans = tp > ans ? tp : ans;
			else ans = tp <ans ? tp : ans;
			
			return ans;
		}
	}
}
